//
//  PlazaChatViewModel.swift
//  NDAi
//
//  Created by 丸子 on 2024/6/28.
//

import UIKit

class PlazaChatViewModel: NSObject {
    var messageList:[AIMessage] = []
    var dataId:String = ""
    var question:String?
    var answer:String?
    var messageStateSubject = PublishSubject<Void>()
    let messageEventSubject = PublishSubject<(Int, String?)>()
    var realtimeMessage:AIStreamMessage?
    var isGenerated:Bool = false {
        didSet {
            self.messageStateSubject.onNext(())
        }
    }
    

    
    func getDataSource() {
        self.messageList = SqlManager.shared.filter(from: AIMessage.self, where: AIMessage.Properties.dataId == dataId) ?? []
        let reversedDataArr = self.messageList.reversed()
        let sortedDataArr = reversedDataArr.sorted { $0.sort ?? 0 < $1.sort ?? 0}
        self.messageList = sortedDataArr
        
        if let model = messageList.first(where: { $0.fromUser == false }) {
            self.messageEventSubject.onNext((1, nil))
        }else {
            if let question = self.question {
                var m = AIMessage()
                m.dataId = self.dataId
                m.userId = Appearance.shared.accoutModel?.userId ?? 0
                m.message = question
                m.state = 0
                m.fromUser = true
                SqlManager.shared.insert([m])
            }
            self.addQa(question: self.question ?? "", answer: self.answer ?? "")
        }
        
//        if self.messageList.count <= 1 {
//           
//        }else {
//        }
    }
    
    func checkWords(message:String){
        guard !isGenerated else { return }
        if !Appearance.shared.isLoign { return }
        isGenerated = true
        let formUserMsg:AIMessage = AIMessage(userId: Appearance.shared.accoutModel?.userId ?? 0, fromUser: true, message: message, dataId: self.dataId)
        self.messageList.append(formUserMsg)
        SqlManager.shared.insert([formUserMsg])
        self.messageEventSubject.onNext((1, nil))
        let thinkingMsg:AIMessage = AIMessage(userId: Appearance.shared.accoutModel?.userId ?? 0, fromUser: false, message: "思考中...")
        self.messageList.append(thinkingMsg)
        self.messageEventSubject.onNext((1, nil))
        RequestService.instance.checkKeyword(message: message) { check in
            if check {
                self.errorCheck(message: message)
                NDProgressHUD.showError(title: "", subtitle: "你输入的内容包含违禁词，请输入输入.")
            }else {
                self.startChat(message: message)
            }
        } failureClosure: { error in
            self.isGenerated = false
        }
    }
    
    
    func startChat(message:String) {
        RequestService.instance.chat_v2(message: message, dataType: 1, dataId: self.dataId) { data in
            self.isGenerated = false
            if let message = data {
                self.startRealtimeTimer(latestMessage: message)
            }else {
                self.errorCheck(message: message)
            }
        } failureClosure: { error in
            self.errorCheck(message: message)
            self.isGenerated = false
        }
    }
    
    func addQa(question:String, answer:String){
        guard !isGenerated else {
            return
        }
        isGenerated = true
        let formUserMsg:AIMessage = AIMessage(userId: Appearance.shared.accoutModel?.userId ?? 0, fromUser: true, message: question)
        self.messageList.append(formUserMsg)
        self.messageEventSubject.onNext((1, nil))
        let thinkingMsg:AIMessage = AIMessage(userId: 0, fromUser: false, message: "思考中...")
        self.messageList.append(thinkingMsg)
        self.messageEventSubject.onNext((1, nil))
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
            var m = AIStreamMessage()
            m.identify = UUID().uuidString
            m.event = "add"
            m.data = answer
            self.startRealtimeTimer(latestMessage: m)
        }
       
    }
    
    func errorCheck(message:String){
        self.isGenerated = false
        self.messageList.removeLast()
        if let models = SqlManager.shared.filter(from: AIMessage.self, where: AIMessage.Properties.message == message), var model = models.first {
            model.state = 3
            SqlManager.shared.update(on: [AIMessage.Properties.state], with: model, where: AIMessage.Properties.sort == model.sort ?? 0)
        }
        if let index = self.messageList.lastIndex(where: { $0.message == message }) {
            self.messageList[index].state = 3
        }
        self.messageEventSubject.onNext((-1, nil))
    }
    
    
    var realtimeTimer: Timer?
    func stopTimer() {
        realtimeTimer?.invalidate()
        realtimeTimer = nil
    }
    
    func startRealtimeTimer(latestMessage: AIStreamMessage?) {
        guard let latestMessage = latestMessage else { return }
        stopTimer()
        var location = 0
        realtimeTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] timer in
            guard let self = self else { return }
            var content = ""
            var isFinished = false
            let speedLength = Int.random(in: 3...8)
            if location < latestMessage.data.count {
                // 计算要提取的子字符串的长度
                let length = min(speedLength, latestMessage.data.count - location)
                // 提取子字符串
                let startIndex = latestMessage.data.index(latestMessage.data.startIndex, offsetBy: location)
                let endIndex = latestMessage.data.index(startIndex, offsetBy: length)
                content = String(latestMessage.data[startIndex..<endIndex])
                location += length
                // 检查是否已完成
                isFinished = latestMessage.status == .finish && location >= latestMessage.data.count
            }
            var m = AIStreamMessage()
            m.identify = UUID().uuidString
            m.event = isFinished ? "finish" : "add"
            m.data = content
            let sm = self.realtimeMessage?.merge(m) ?? m
            self.realtimeMessage = sm
            updateStreamContent(message: sm, isDone: false)
            if sm.status == .finish || sm.data.count == latestMessage.data.count || location >= latestMessage.data.count {
                updateStreamContent(message: sm, isDone: true)
                self.realtimeMessage = nil
                self.isGenerated = false
                timer.invalidate()
            }
        }
    }
    
    func updateStreamContent(message:AIStreamMessage, isDone:Bool){
        var m = AIMessage.convert(from: message)
        if isDone {
            m.dataId = self.dataId
            SqlManager.shared.insert([m])
        }else {
            if !self.messageList.isEmpty {
                self.messageList[self.messageList.count - 1] = m
            } else {
                self.messageList.append(m)
            }
            self.messageEventSubject.onNext((1, nil))
        }
    }
    
}
